package controllers

import java.nio.file.{Files, Paths}
import javax.inject.Inject
import play.api.mvc._
import models.Tables._
import dao._
import test.Test.map

import java.io.File
import scala.concurrent.Await
import scala.io.Source
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.collection.JavaConverters._
import implicits.Implicits._


/**
 * Created by yz on 2017/6/1.
 */
class DataInsertController @Inject()(browseLongRnaDao: BrowseLongRnaDao,
                                     circAllPositionsDao: BrowseCircRnaDao, cirRNAProfileDao: CirRNAProfileDao,
                                     longRNAProfileDao: LongRNAProfileDao,
                                     cc: ControllerComponents)(
                                      implicit val browsePathwayDao: BrowsePathwayDao,
                                      implicit val browseCellDao: BrowseCellDao,
                                      implicit val detailLongRnaDao: DetailLongRnaDao,
                                      implicit val detailCircRnaDao: DetailCircRnaDao,
                                    )
  extends AbstractController(cc) {

  val parentDir = new File("E:\\exorbase_v2_database\\test")

  def insertBrowseLongRna = Action.async {
    val startTime = System.currentTimeMillis()
    val file = new File(parentDir, "browse_longRNA.txt")
    val maps = file.txtLines.lineSeqMap
    val rows = maps.map { map =>
      BrowseLongRnaRow(
        geneName = map("Gene symbol"),
        geneId = map("Gene ID"),
        geneType = map("Gene type"),
        related = map("Related circRNA").toInt,
        detectionFrequency = map("Detection frequency").toDouble,
        tissueSpecificity = map("Tissue specificity"),
        specificityScore = map("Specificity score"),
        sampleType = map("Sample type"),
        tumorMean = map("Tumor mean").toDouble,
        benignMean = map("Benign mean").toDouble,
        healthMean = map("Healthy mean").toDouble,
        urineMean = map("Urine mean").toDouble,
        csfMean = map("CSF mean").toDouble,
        bileMean = map("Bile mean").toDouble,
        diffGroup = map("Diff group")
      )
    }
    browseLongRnaDao.deleteAll().flatMap(_ => browseLongRnaDao.insertAll(rows)).map { _ =>
      Ok("success!" + "\t" + rows.size + "\t" + getTime(startTime))
    }
  }

  def insertBrowseCircRnas = Action.async {
    val startTime = System.currentTimeMillis()
    val file = new File(parentDir, "browse_circRNA.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      val position = map("Genomic position")
      val chr = position.split(":")(0)
      val start = position.split(":")(1).split("-")(0)
      val end = position.split(":")(1).split("-")(1)
      BrowseCircRnaRow(
        circId = map("circID"),
        circBaseId = map("circBase ID"),
        chromosome = chr,
        start = start.toInt,
        end = end.toInt,
        strand = map("Strand"),
        geneSymbol = map("Gene symbol"),
        geneType = map("Gene type"),
        detectionFrequency = map("Detection frequency").toDouble,
        sampleType = map("Sample type"),
        tumorMean = map("Tumor mean").toDouble,
        benignMean = map("Benign mean").toDouble,
        healthMean = map("Healthy mean").toDouble,
        urineMean = map("Urine mean").toDouble,
        csfMean = map("CSF mean").toDouble,
        bileMean = map("Bile mean").toDouble,
        diffGroup = map("Diff group"),
        genomicPosition = map("Genomic position")
      )
    }
    circAllPositionsDao.deleteAll().flatMap(_ => circAllPositionsDao.insertAll(rows)).map { x =>
      Ok("success!" + "\t" + rows.size + "\t" + getTime(startTime))
    }
  }

  def insertBrowsePathway = Action.async {
    val startTime = System.currentTimeMillis()
    val file = new File(parentDir, "browse_pathway.txt")
    val rows = file.txtLines.map(_.map(_.trim)).lineSeqMap.map { map =>
      BrowsePathwayRow(
        pathwayId = map("Pathway ID"),
        pathwayName = map("Pathway name"),
        msigdbSource = map("MSigDB source"),
        tumorMean = map("Tumor mean").toDouble,
        benignMean = map("Benign mean").toDouble,
        healthMean = map("Healthy mean").toDouble,
        urineMean = map("Urine mean").toDouble,
        csfMean = map("CSF mean").toDouble,
        bileMean = map("Bile mean").toDouble,
        msigdbLink = map("MSigDB link"),
        diffGroup = map("Diff group"),
      )
    }
    browsePathwayDao.deleteAll().flatMap(_ => browsePathwayDao.insertAll(rows)).map { x =>
      Ok("success!" + "\t" + rows.size + "\t" + getTime(startTime))
    }
  }

  def insertBrowseCell = Action.async {
    val startTime = System.currentTimeMillis()
    val file = new File(parentDir, "browse_cell.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      BrowseCellRow(
        cellName = map("Cell name"),
        cellDescription = map("Cell description"),
        cellOrigin = map("Cell origin"),
        cellType = map("Cell type"),
        tumorMean = map("Tumor mean").toDouble,
        benignMean = map("Benign mean").toDouble,
        healthMean = map("Healthy mean").toDouble,
        urineMean = map("Urine mean").toDouble,
        csfMean = map("CSF mean").toDouble,
        bileMean = map("Bile mean").toDouble,
        diffGroup = map("Diff group"),
      )
    }
    browseCellDao.deleteAll().flatMap(_ => browseCellDao.insertAll(rows)).map { x =>
      Ok("success!" + "\t" + rows.size + "\t" + getTime(startTime))
    }
  }

  def insertDetailLongRna = Action.async {
    val startTime = System.currentTimeMillis()
    val file = new File(parentDir, "detail_longRNA.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      DetailLongRnaRow(
        geneName = map("Gene symbol"),
        geneId = map("Gene ID"),
        fullName = map("Full name"),
        geneType = map("Gene type"),
        genomicPosition = map("Genomic position"),
        strand = map("Strand"),
        length = map("Length").toInt,
        geneCards = map("Gene cards"),
        related = map("Related circRNA").toInt,
        tissueSpecificity = map("Tissue specificity"),
        specificityScore = map("Specificity score"),
        sampleType = map("Sample type"),
        tumorFrequency = map("Tumor frequency (Sample number)"),
        benignFrequency = map("Benign frequency (Sample number)"),
        healthFrequency = map("Healthy frequency (Sample number)"),
        urineFrequency = map("Urine frequency (Sample number)"),
        csfFrequency = map("CSF frequency (Sample number)"),
        bileFrequency = map("Bile frequency (Sample number)"),
        tumorMean = map("Tumor mean").toDouble,
        benignMean = map("Benign mean").toDouble,
        healthMean = map("Healthy mean").toDouble,
        urineMean = map("Urine mean").toDouble,
        csfMean = map("CSF mean").toDouble,
        bileMean = map("Bile mean").toDouble,
        diffGroup = map("Diff group")
      )
    }
    detailLongRnaDao.deleteAll().flatMap(_ => detailLongRnaDao.insertAll(rows)).map { x =>
      Ok("success!" + "\t" + rows.size + "\t" + getTime(startTime))
    }
  }

  def insertDetailCircRna = Action.async {
    val startTime = System.currentTimeMillis()
    val file = new File(parentDir, "detail_circRNA.txt")
    val rows = file.txtLines.lineSeqMap.map { map =>
      DetailCircRnaRow(
        circId = map("circID"),
        circBaseId = map("circBase ID"),
        genomicPosition = map("Genomic position"),
        strand = map("Strand"),
        genomicLength = map("Genomic length").toInt,
        splicedLength = map("Spliced length"),
        geneSymbol = map("Gene symbol"),
        geneType = map("Gene type"),
        sampleType = map("Sample type"),
        tumorFrequency = map("Tumor frequency (Sample number)"),
        benignFrequency = map("Benign frequency (Sample number)"),
        healthFrequency = map("Healthy frequency (Sample number)"),
        urineFrequency = map("Urine frequency (Sample number)"),
        csfFrequency = map("CSF frequency (Sample number)"),
        bileFrequency = map("Bile frequency (Sample number)"),
        tumorMean = map("Tumor mean").toDouble,
        benignMean = map("Benign mean").toDouble,
        healthMean = map("Healthy mean").toDouble,
        urineMean = map("Urine mean").toDouble,
        csfMean = map("CSF mean").toDouble,
        bileMean = map("Bile mean").toDouble,
        diffGroup = map("Diff group"))
    }
    detailCircRnaDao.deleteAll().flatMap(_ => detailCircRnaDao.insertAll(rows)).map { x =>
      Ok("success!" + "\t" + rows.size + "\t" + getTime(startTime))
    }
  }

  def insertCircRNAProfile() = Action {
    val startTime = System.currentTimeMillis()

    Await.result(cirRNAProfileDao.dropTable(), Duration.Inf)
    println("drop table successfully!" + getTime(startTime))
    Await.result(cirRNAProfileDao.createTable(), Duration.Inf)
    println("create table successfully!" + getTime(startTime))

    val newBuffer = Files.readAllLines(Paths.get("D:\\迅雷下载\\数据\\Expression_profiles\\Samples_combined_circRNA_RPM1.txt")).asScala
    val buffer1 = newBuffer.drop(1).map(_.split("\t")(0)).zip(newBuffer.drop(1)).toMap
    val buffer = buffer1.values.toBuffer

    val header = newBuffer.take(1).flatMap(_.split("\t"))
    val rows = buffer.drop(1).flatMap { x =>
      val columns = x.split("\t")
      columns.drop(1).zipWithIndex.map {
        case (value, index) =>
          CircrnaprofileRow(columns(0), header(index + 1), value.toDouble, map(header(index + 1)))
      }
    }
    println("read line successfully!" + getTime(startTime))
    val rowsSize = rows.size
    val num = 50000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(cirRNAProfileDao.insertAll(x.toList), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + getTime(startTime))
    }
    println("insert table successfully!" + getTime(startTime))
    Ok("success!")

  }

  def insertLongRNAProfile() = Action {
    val startTime = System.currentTimeMillis()
    //    Await.result(longRNAProfileDao.dropTable(), Duration.Inf)
    //    println("drop table successfully!" + getTime(startTime))
    //    Await.result(longRNAProfileDao.createTable(), Duration.Inf)
    //    println("create table successfully!" + getTime(startTime))

    //    val newBuffer = Files.readAllLines(Paths.get("D:\\迅雷下载\\数据更新20170907\\Samples_combined_lncRNA_TPM.txt")).asScala
    val newBuffer = Files.readAllLines(Paths.get("D:\\迅雷下载\\数据更新20170907\\Samples_combined_mRNA_TPM.txt")).asScala
    val buffer1 = newBuffer.drop(1).map(_.split("\t")(0)).zip(newBuffer.drop(1)).toMap
    val buffer = buffer1.values.toBuffer
    val header = newBuffer.take(1).flatMap(_.split("\t"))
    val rows = buffer.drop(1).flatMap { x =>
      val columns = x.split("\t")
      columns.drop(1).zipWithIndex.map {
        case (value, index) =>
          LongrnaprofileRow(columns(0), header(index + 1), value.toDouble, map(header(index + 1)))
      }
    }
    println("read line successfully!" + getTime(startTime))
    val rowsSize = rows.size
    val num = 50000
    var index = 0
    rows.grouped(num).foreach { x =>
      Await.result(longRNAProfileDao.insertAll(x.toList), Duration.Inf)
      index = index + 1
      val percent = if ((index * num * 100) / rowsSize >= 100) "100%" else (index * num * 100) / rowsSize + "%"
      println(percent + "\t" + getTime(startTime))
    }
    println("insert table successfully!" + getTime(startTime))
    Ok("success!")
  }

  def getTime(startTime: Long) = {
    val endTime = System.currentTimeMillis()
    (endTime - startTime) / 1000.0
  }

}
